/*
 * protect.c
 *
 *  Created on: 2016-10-14
 *      Author: m
 */
#include "protect.h"
#include "string.h"
#include "global.h"
#include "kernel.h"
#include "i8259.h"

void init_idt_desc(u8 idx, u8 desc_type, int_handler handler, u8 privilege) {
    GATE *  p_gate  = &g_idt[idx];
    u32 base    = (u32)handler;
    p_gate->offset_low  = base & 0xFFFF;
    p_gate->selector    = 8;
    p_gate->dcount      = 0;
    p_gate->attr        = desc_type | (privilege << 5);
    p_gate->offset_high = (base >> 16) & 0xFFFF;
}

void init_descriptor(DESCRIPTOR *p_desc,void* base,u32 limit,u16 attribute) {
    p_desc->limit_low   = limit & 0x0FFFF;
    p_desc->base_low    = (u32)base & 0x0FFFF;
    p_desc->base_mid    = ((u32)base >> 16) & 0x0FF;
    p_desc->attr1       = attribute & 0xFF;
    p_desc->limit_high_attr2= ((limit>>16) & 0x0F) | ((attribute>>8) & 0xF0);
    p_desc->base_high   = ((u32)base >> 24) & 0x0FF;
}

void init_prot() {
    init_8259A();

    // 全部初始化成中断门(没有陷阱门)
    init_idt_desc(INT_0VECTOR_DIVIDE, DA_386IGate, divide_error, PRIVILEGE_KRNL);
    init_idt_desc(INT_1VECTOR_DEBUG, DA_386IGate, single_step_exception, PRIVILEGE_KRNL);
    init_idt_desc(INT_2VECTOR_NMI, DA_386IGate, nmi, PRIVILEGE_KRNL);
    init_idt_desc(INT_3VECTOR_BREAKPOINT, DA_386IGate, breakpoint_exception, PRIVILEGE_USER);
    init_idt_desc(INT_4VECTOR_OVERFLOW, DA_386IGate, overflow, PRIVILEGE_USER);
    init_idt_desc(INT_5VECTOR_BOUNDS, DA_386IGate, bounds_check, PRIVILEGE_KRNL);
    init_idt_desc(INT_6VECTOR_INVAL_OP, DA_386IGate, inval_opcode, PRIVILEGE_KRNL);
    init_idt_desc(INT_7VECTOR_COPROC_NOT, DA_386IGate, copr_not_available, PRIVILEGE_KRNL);
    init_idt_desc(INT_8VECTOR_DOUBLE_FAULT, DA_386IGate, double_fault, PRIVILEGE_KRNL);
    init_idt_desc(INT_9VECTOR_COPROC_SEG, DA_386IGate, copr_seg_overrun, PRIVILEGE_KRNL);
    init_idt_desc(INT_AVECTOR_INVAL_TSS, DA_386IGate, inval_tss, PRIVILEGE_KRNL);
    init_idt_desc(INT_BVECTOR_SEG_NOT, DA_386IGate, segment_not_present, PRIVILEGE_KRNL);
    init_idt_desc(INT_CVECTOR_STACK_FAULT, DA_386IGate, stack_exception, PRIVILEGE_KRNL);
    init_idt_desc(INT_DVECTOR_PROTECTION, DA_386IGate, general_protection, PRIVILEGE_KRNL);
    init_idt_desc(INT_EVECTOR_PAGE_FAULT, DA_386IGate, page_fault, PRIVILEGE_KRNL);
    init_idt_desc(INT_10VECTOR_COPROC_ERR, DA_386IGate, copr_error, PRIVILEGE_KRNL);

    init_idt_desc(INT_INDEX20_IRQ0 + 0, DA_386IGate, hwint00, PRIVILEGE_KRNL);
    init_idt_desc(INT_INDEX20_IRQ0 + 1, DA_386IGate, hwint01, PRIVILEGE_KRNL);
    init_idt_desc(INT_INDEX20_IRQ0 + 2, DA_386IGate, hwint02, PRIVILEGE_KRNL);
    init_idt_desc(INT_INDEX20_IRQ0 + 3, DA_386IGate, hwint03, PRIVILEGE_KRNL);
    init_idt_desc(INT_INDEX20_IRQ0 + 4, DA_386IGate, hwint04, PRIVILEGE_KRNL);
    init_idt_desc(INT_INDEX20_IRQ0 + 5, DA_386IGate, hwint05, PRIVILEGE_KRNL);
    init_idt_desc(INT_INDEX20_IRQ0 + 6, DA_386IGate, hwint06, PRIVILEGE_KRNL);
    init_idt_desc(INT_INDEX20_IRQ0 + 7, DA_386IGate, hwint07, PRIVILEGE_KRNL);
    init_idt_desc(INT_INDEX20_IRQ0 + 8, DA_386IGate, hwint08, PRIVILEGE_KRNL);
    init_idt_desc(INT_INDEX20_IRQ0 + 9, DA_386IGate, hwint09, PRIVILEGE_KRNL);
    init_idt_desc(INT_INDEX20_IRQ0 + 10, DA_386IGate, hwint0a, PRIVILEGE_KRNL);
    init_idt_desc(INT_INDEX20_IRQ0 + 11, DA_386IGate, hwint0b, PRIVILEGE_KRNL);
    init_idt_desc(INT_INDEX20_IRQ0 + 12, DA_386IGate, hwint0c, PRIVILEGE_KRNL);
    init_idt_desc(INT_INDEX20_IRQ0 + 13, DA_386IGate, hwint0d, PRIVILEGE_KRNL);
    init_idt_desc(INT_INDEX20_IRQ0 + 14, DA_386IGate, hwint0e, PRIVILEGE_KRNL);
    init_idt_desc(INT_INDEX20_IRQ0 + 15, DA_386IGate, hwint0f, PRIVILEGE_KRNL);

    init_idt_desc(INT_VECTOR_SYSCALL, DA_386IGate, sys_call, PRIVILEGE_USER);

    memset(&g_tss, 0, sizeof(g_tss));
    g_tss.ss0 = SELECTOR_KERNEL_DS;
    init_descriptor(&g_gdt[INDEX_TSS], &g_tss, sizeof(g_tss) - 1, DA_386TSS);
    g_tss.iobase = sizeof(g_tss); /* 没有I/O许可位图 */
}

